package com.szr.leex.dao.converter;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Objects;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;

import com.szr.leex.dao.converter.type.java.WeekTypeDescriptor;
import com.szr.leex.po.enums.WeekEnum;

import lombok.extern.slf4j.Slf4j;

/**
 * week type
 * 两种类型的custom basic type 之二, extend UserType
 * Created by WangChen on 2018/9/9 16:35.
 */
@Slf4j
public class WeekType implements UserType {

    public static final WeekType INSTANCE = new WeekType();

    @Override
    public int[] sqlTypes() {
        return new int[]{Types.VARCHAR};
    }

    @Override
    public Class returnedClass() {
        return WeekEnum.class;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        return Objects.equals( x, y );
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return Objects.hashCode( x );
    }

    /**
     * from jdbc type value to java type value
     */
    @Override
    public Object nullSafeGet(ResultSet resultSet, String[] strings, SharedSessionContractImplementor sharedSessionContractImplementor,
                              Object o) throws HibernateException, SQLException {
        String columnName = strings[0];
        String columnValue = (String) resultSet.getObject( columnName );
        log.debug("resultSet column {0} value is {1}", columnName, columnValue);
        return columnValue == null ? null : WeekTypeDescriptor.INSTANCE.fromString( columnValue );
    }

    @Override
    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SharedSessionContractImplementor sharedSessionContractImplementor)
            throws HibernateException, SQLException {
        if ( value == null ) {
            log.debug("Binding null to parameter {0} ",index);
            preparedStatement.setNull( index, Types.VARCHAR );
        }else {
            String stringValue = WeekTypeDescriptor.INSTANCE.toString((WeekEnum) value);
            log.debug("Binding {0} to parameter {1} ", stringValue, index);
            preparedStatement.setString( index, stringValue );
        }
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    @Override
    public boolean isMutable() {
        return true;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) deepCopy(value);
    }

    @Override
    public Object assemble(Serializable serializable, Object o) throws HibernateException {
        return deepCopy(serializable);
    }

    @Override
    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return deepCopy(original);
    }
}
